﻿using System;
using GeoAPI.Geometries;

namespace YJKGridTopologyCal.Algorithm
{
	public class RobustLineIntersector : LineIntersector
	{
		public override void ComputeIntersection(Coordinate p, Coordinate p1, Coordinate p2)
		{
			base.IsProper = false;
			if (Envelope.Intersects(p1, p2, p) && CGAlgorithms.OrientationIndex(p1, p2, p) == 0 && CGAlgorithms.OrientationIndex(p2, p1, p) == 0)
			{
				base.IsProper = true;
				if (p.Equals(p1) || p.Equals(p2))
				{
					base.IsProper = false;
				}
				this.Result = LineIntersector.PointIntersection;
				return;
			}
			this.Result = LineIntersector.NoIntersection;
		}

		public override int ComputeIntersect(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			base.IsProper = false;
			if (!Envelope.Intersects(p1, p2, q1, q2))
			{
				return LineIntersector.NoIntersection;
			}
			int num = CGAlgorithms.OrientationIndex(p1, p2, q1);
			int num2 = CGAlgorithms.OrientationIndex(p1, p2, q2);
			if ((num > 0 && num2 > 0) || (num < 0 && num2 < 0))
			{
				return LineIntersector.NoIntersection;
			}
			int num3 = CGAlgorithms.OrientationIndex(q1, q2, p1);
			int num4 = CGAlgorithms.OrientationIndex(q1, q2, p2);
			if ((num3 > 0 && num4 > 0) || (num3 < 0 && num4 < 0))
			{
				return LineIntersector.NoIntersection;
			}
			if (num == 0 && num2 == 0 && num3 == 0 && num4 == 0)
			{
				return this.ComputeCollinearIntersection(p1, p2, q1, q2);
			}
			if (num == 0 || num2 == 0 || num3 == 0 || num4 == 0)
			{
				base.IsProper = false;
				if (p1.Equals2D(q1) || p1.Equals2D(q2))
				{
					this.IntersectionPoint[0] = p1;
				}
				else if (p2.Equals2D(q1) || p2.Equals2D(q2))
				{
					this.IntersectionPoint[0] = p2;
				}
				else if (num == 0)
				{
					this.IntersectionPoint[0] = new Coordinate(q1);
				}
				else if (num2 == 0)
				{
					this.IntersectionPoint[0] = new Coordinate(q2);
				}
				else if (num3 == 0)
				{
					this.IntersectionPoint[0] = new Coordinate(p1);
				}
				else if (num4 == 0)
				{
					this.IntersectionPoint[0] = new Coordinate(p2);
				}
			}
			else
			{
				base.IsProper = true;
				this.IntersectionPoint[0] = this.Intersection(p1, p2, q1, q2);
			}
			return LineIntersector.PointIntersection;
		}

		private int ComputeCollinearIntersection(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			bool flag = Envelope.Intersects(p1, p2, q1);
			bool flag2 = Envelope.Intersects(p1, p2, q2);
			bool flag3 = Envelope.Intersects(q1, q2, p1);
			bool flag4 = Envelope.Intersects(q1, q2, p2);
			if (flag && flag2)
			{
				this.IntersectionPoint[0] = q1;
				this.IntersectionPoint[1] = q2;
				return LineIntersector.CollinearIntersection;
			}
			if (flag3 && flag4)
			{
				this.IntersectionPoint[0] = p1;
				this.IntersectionPoint[1] = p2;
				return LineIntersector.CollinearIntersection;
			}
			if (flag && flag3)
			{
				this.IntersectionPoint[0] = q1;
				this.IntersectionPoint[1] = p1;
				if (!q1.Equals(p1))
				{
					return LineIntersector.CollinearIntersection;
				}
				return LineIntersector.PointIntersection;
			}
			else if (flag && flag4)
			{
				this.IntersectionPoint[0] = q1;
				this.IntersectionPoint[1] = p2;
				if (!q1.Equals(p2))
				{
					return LineIntersector.CollinearIntersection;
				}
				return LineIntersector.PointIntersection;
			}
			else if (flag2 && flag3)
			{
				this.IntersectionPoint[0] = q2;
				this.IntersectionPoint[1] = p1;
				if (!q2.Equals(p1))
				{
					return LineIntersector.CollinearIntersection;
				}
				return LineIntersector.PointIntersection;
			}
			else
			{
				if (!flag2 || !flag4)
				{
					return LineIntersector.NoIntersection;
				}
				this.IntersectionPoint[0] = q2;
				this.IntersectionPoint[1] = p2;
				if (!q2.Equals(p2))
				{
					return LineIntersector.CollinearIntersection;
				}
				return LineIntersector.PointIntersection;
			}
		}

		private Coordinate Intersection(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			Coordinate coordinate = this.IntersectionWithNormalization(p1, p2, q1, q2);
			if (!this.IsInSegmentEnvelopes(coordinate))
			{
				coordinate = new Coordinate(RobustLineIntersector.NearestEndpoint(p1, p2, q1, q2));
			}
			if (base.PrecisionModel != null)
			{
				base.PrecisionModel.MakePrecise(coordinate);
			}
			return coordinate;
		}

		private void CheckDD(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2, Coordinate intPt)
		{
			Coordinate coordinate = CGAlgorithmsDD.Intersection(p1, p2, q1, q2);
			this.IsInSegmentEnvelopes(coordinate);
			intPt.Distance(coordinate);
		}

		private Coordinate IntersectionWithNormalization(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			Coordinate coordinate = new Coordinate(p1);
			Coordinate coordinate2 = new Coordinate(p2);
			Coordinate coordinate3 = new Coordinate(q1);
			Coordinate coordinate4 = new Coordinate(q2);
			Coordinate coordinate5 = new Coordinate();
			this.NormalizeToEnvCentre(coordinate, coordinate2, coordinate3, coordinate4, coordinate5);
			Coordinate coordinate6 = RobustLineIntersector.SafeHCoordinateIntersection(coordinate, coordinate2, coordinate3, coordinate4);
			coordinate6.X += coordinate5.X;
			coordinate6.Y += coordinate5.Y;
			return coordinate6;
		}

		private static Coordinate SafeHCoordinateIntersection(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			Coordinate result;
			try
			{
				result = HCoordinate.Intersection(p1, p2, q1, q2);
			}
			catch (NotRepresentableException)
			{
				result = RobustLineIntersector.NearestEndpoint(p1, p2, q1, q2);
			}
			return result;
		}

		private void NormalizeToEnvCentre(Coordinate n00, Coordinate n01, Coordinate n10, Coordinate n11, Coordinate normPt)
		{
			double num = (n00.X < n01.X) ? n00.X : n01.X;
			double num2 = (n00.Y < n01.Y) ? n00.Y : n01.Y;
			double num3 = (n00.X > n01.X) ? n00.X : n01.X;
			double num4 = (n00.Y > n01.Y) ? n00.Y : n01.Y;
			double num5 = (n10.X < n11.X) ? n10.X : n11.X;
			double num6 = (n10.Y < n11.Y) ? n10.Y : n11.Y;
			double num7 = (n10.X > n11.X) ? n10.X : n11.X;
			double num8 = (n10.Y > n11.Y) ? n10.Y : n11.Y;
			double num9 = (num > num5) ? num : num5;
			double num10 = (num3 < num7) ? num3 : num7;
			double num11 = (num2 > num6) ? num2 : num6;
			double num12 = (num4 < num8) ? num4 : num8;
			double x = (num9 + num10) / 2.0;
			double y = (num11 + num12) / 2.0;
			normPt.X = x;
			normPt.Y = y;
			n00.X -= normPt.X;
			n00.Y -= normPt.Y;
			n01.X -= normPt.X;
			n01.Y -= normPt.Y;
			n10.X -= normPt.X;
			n10.Y -= normPt.Y;
			n11.X -= normPt.X;
			n11.Y -= normPt.Y;
		}

		private bool IsInSegmentEnvelopes(Coordinate intPoint)
		{
			Envelope envelope = new Envelope(this.InputLines[0][0], this.InputLines[0][1]);
			Envelope envelope2 = new Envelope(this.InputLines[1][0], this.InputLines[1][1]);
			return envelope.Contains(intPoint) && envelope2.Contains(intPoint);
		}

		private static Coordinate NearestEndpoint(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2)
		{
			Coordinate result = p1;
			double num = CGAlgorithms.DistancePointLine(p1, q1, q2);
			double num2 = CGAlgorithms.DistancePointLine(p2, q1, q2);
			if (num2 < num)
			{
				num = num2;
				result = p2;
			}
			num2 = CGAlgorithms.DistancePointLine(q1, p1, p2);
			if (num2 < num)
			{
				num = num2;
				result = q1;
			}
			num2 = CGAlgorithms.DistancePointLine(q2, p1, p2);
			if (num2 < num)
			{
				result = q2;
			}
			return result;
		}
	}
}
